package com.pllandxzx.controller;

import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.fasterxml.jackson.databind.ObjectMapper;

@ServerEndpoint("/ws/chat/{identity}/{id}")
@Component
public class ChatServerEndpoint {

    private static final Logger log = LoggerFactory.getLogger(ChatServerEndpoint.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 存储用户的WebSocket会话，Key是userId
     */
    private static final Map<Long, Session> userSessions = new ConcurrentHashMap<>();

    /**
     * 存储商家的WebSocket会话，Key是merchantId
     */
    private static final Map<Long, Session> merchantSessions = new ConcurrentHashMap<>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("identity") String identity, @PathParam("id") Long id) {
        if ("user".equalsIgnoreCase(identity)) {
            userSessions.put(id, session);
            log.info("用户 {} 连接成功。当前在线用户数: {}", id, userSessions.size());
        } else if ("merchant".equalsIgnoreCase(identity)) {
            merchantSessions.put(id, session);
            log.info("商家 {} 连接成功。当前在线商家数: {}", id, merchantSessions.size());
        } else {
            log.warn("未知的连接身份: {}", identity);
            try {
                session.close();
            } catch (IOException e) {
                log.error("关闭未知身份的连接时出错", e);
            }
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("identity") String identity, @PathParam("id") Long id) {
        if ("user".equalsIgnoreCase(identity)) {
            userSessions.remove(id);
            log.info("用户 {} 连接关闭。当前在线用户数: {}", id, userSessions.size());
        } else if ("merchant".equalsIgnoreCase(identity)) {
            merchantSessions.remove(id);
            log.info("商家 {} 连接关闭。当前在线商家数: {}", id, merchantSessions.size());
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("identity") String identity, @PathParam("id") Long fromId) {
        log.info("收到来自 {} {} 的消息: {}", identity, fromId, message);
        try {
            MessagePayload payload = objectMapper.readValue(message, MessagePayload.class);
            routeMessage(payload, fromId);
        } catch (IOException e) {
            log.error("解析消息失败: {}", message, e);
            sendMessage(session, "错误：无效的消息格式。");
        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket发生错误", error);
    }

    /**
     * 消息路由核心逻辑
     */
    private void routeMessage(MessagePayload payload, Long fromId) {
        String content = payload.getContent();
        Long toId = payload.getToId();
        String toType = payload.getToType();

        Session targetSession = null;
        if ("user".equalsIgnoreCase(toType)) {
            targetSession = userSessions.get(toId);
        } else if ("merchant".equalsIgnoreCase(toType)) {
            targetSession = merchantSessions.get(toId);
        }

        if (targetSession != null && targetSession.isOpen()) {
            // 为了安全，我们只转发内容，也可以选择转发包含来源ID的更复杂对象
            sendMessage(targetSession, content);
            log.info("已将来自 {} 的消息转发给 {} {}", fromId, toType, toId);
        } else {
            log.warn("消息发送失败：目标 {} {} 不在线。", toType, toId);
            // 可以选择给发送方一个"对方不在线"的回执
            // Session fromSession = "user".equalsIgnoreCase(fromIdentity) ? userSessions.get(fromId) : merchantSessions.get(fromId);
            // sendMessage(fromSession, "对方不在线");
        }
    }

    /**
     * 服务端发送消息给客户端
     */
    private void sendMessage(Session session, String message) {
        try {
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            log.error("发送消息失败", e);
        }
    }
    
    /**
     * 标准化消息载体
     */
    private static class MessagePayload {
        private String toType; // 'user' or 'merchant'
        private Long toId;
        private String content;

        // Getters and Setters
        public String getToType() { return toType; }
        public void setToType(String toType) { this.toType = toType; }
        public Long getToId() { return toId; }
        public void setToId(Long toId) { this.toId = toId; }
        public String getContent() { return content; }
        public void setContent(String content) { this.content = content; }
    }
} 